package metrics

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
)

var (
	// Service metrics
	ServiceStartTime = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_service_start_time_seconds",
		Help: "Unix timestamp of service start time",
	})

	// Snapshot metrics
	SnapshotOperations = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "onyx_snapshot_operations_total",
		Help: "Total number of snapshot operations",
	}, []string{"operation", "status"})

	SnapshotOperationDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
		Name:    "onyx_snapshot_operation_duration_seconds",
		Help:    "Duration of snapshot operations",
		Buckets: prometheus.DefBuckets,
	}, []string{"operation"})

	ActiveSnapshots = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_active_snapshots",
		Help: "Current number of active snapshots",
	})

	// Download metrics
	DownloadOperations = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "onyx_download_operations_total",
		Help: "Total number of download operations",
	}, []string{"status"})

	DownloadBytes = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_download_bytes_total",
		Help: "Total bytes downloaded",
	})

	DownloadDuration = promauto.NewHistogram(prometheus.HistogramOpts{
		Name:    "onyx_download_duration_seconds",
		Help:    "Duration of download operations",
		Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10},
	})

	ActiveDownloads = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_active_downloads",
		Help: "Current number of active downloads",
	})

	// Cache metrics
	CacheHits = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_cache_hits_total",
		Help: "Total number of cache hits",
	})

	CacheMisses = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_cache_misses_total",
		Help: "Total number of cache misses",
	})

	CacheSize = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_cache_size_bytes",
		Help: "Current cache size in bytes",
	})

	CacheItems = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_cache_items",
		Help: "Current number of items in cache",
	})

	CacheEvictions = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_cache_evictions_total",
		Help: "Total number of cache evictions",
	})

	// Deduplication metrics
	DedupChunksTotal = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_dedup_chunks_total",
		Help: "Total number of chunks processed",
	})

	DedupChunksDuplicate = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_dedup_chunks_duplicate_total",
		Help: "Total number of duplicate chunks detected",
	})

	DedupSavedBytes = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_dedup_saved_bytes_total",
		Help: "Total bytes saved through deduplication",
	})

	DedupStoreSize = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_dedup_store_size_bytes",
		Help: "Current deduplication store size in bytes",
	})

	DedupRatio = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_dedup_ratio",
		Help: "Current deduplication ratio (0-1)",
	})

	// Prefetch metrics
	PrefetchOperations = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "onyx_prefetch_operations_total",
		Help: "Total number of prefetch operations",
	}, []string{"status"})

	PrefetchFiles = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_prefetch_files_total",
		Help: "Total number of files prefetched",
	})

	PrefetchBytes = promauto.NewCounter(prometheus.CounterOpts{
		Name: "onyx_prefetch_bytes_total",
		Help: "Total bytes prefetched",
	})

	// Ublk metrics
	UblkRequests = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "onyx_ublk_requests_total",
		Help: "Total number of ublk requests",
	}, []string{"type", "status"})

	UblkRequestDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
		Name:    "onyx_ublk_request_duration_seconds",
		Help:    "Duration of ublk requests",
		Buckets: []float64{.0001, .0005, .001, .005, .01, .05, .1, .5, 1},
	}, []string{"type"})

	UblkDevices = promauto.NewGauge(prometheus.GaugeOpts{
		Name: "onyx_ublk_devices",
		Help: "Current number of ublk devices",
	})

	// Error metrics
	Errors = promauto.NewCounterVec(prometheus.CounterOpts{
		Name: "onyx_errors_total",
		Help: "Total number of errors by type",
	}, []string{"component", "type"})
)

// Initialize registers all metrics
func Initialize() error {
	// All metrics are auto-registered via promauto
	return nil
}

// Helper functions for common metric updates

func RecordSnapshotOperation(operation string, success bool) {
	status := "success"
	if !success {
		status = "error"
	}
	SnapshotOperations.WithLabelValues(operation, status).Inc()
}

func RecordDownload(size int64, success bool) {
	status := "success"
	if !success {
		status = "error"
	}
	DownloadOperations.WithLabelValues(status).Inc()
	if success {
		DownloadBytes.Add(float64(size))
	}
}

func RecordCacheAccess(hit bool) {
	if hit {
		CacheHits.Inc()
	} else {
		CacheMisses.Inc()
	}
}

func UpdateCacheStats(items int, size int64) {
	CacheItems.Set(float64(items))
	CacheSize.Set(float64(size))
}

func RecordDedupChunk(isDuplicate bool, size int64) {
	DedupChunksTotal.Inc()
	if isDuplicate {
		DedupChunksDuplicate.Inc()
		DedupSavedBytes.Add(float64(size))
	}
}

func UpdateDedupRatio(ratio float64) {
	DedupRatio.Set(ratio)
}

func RecordPrefetch(files int, bytes int64, success bool) {
	status := "success"
	if !success {
		status = "error"
	}
	PrefetchOperations.WithLabelValues(status).Inc()
	if success {
		PrefetchFiles.Add(float64(files))
		PrefetchBytes.Add(float64(bytes))
	}
}

func RecordUblkRequest(reqType string, success bool) {
	status := "success"
	if !success {
		status = "error"
	}
	UblkRequests.WithLabelValues(reqType, status).Inc()
}

func RecordError(component, errType string) {
	Errors.WithLabelValues(component, errType).Inc()
}
